package com.js.admin.service.impl;

import com.js.admin.constant.AdminConstant;
import com.js.admin.entity.*;
import com.js.admin.mapper.*;
import com.js.admin.service.BaseAppOrderService;
import com.js.admin.service.BaseGroupService;
import com.js.admin.service.BaseResourceAuthorityService;
import com.js.admin.vo.GroupUsers;
import com.js.admin.vo.MenuTree;
import com.js.common.exception.auth.ClientTokenException;
import com.js.common.service.impl.BizServiceImpl;
import com.js.common.util.BooleanUtil;
import com.js.common.util.SnowFlakeUtil;
import com.js.core.context.BaseContextHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.*;

/**
 * @author： ygl
 * @date： 2018/3/26
 * @Description：
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class BaseGroupServiceImpl extends BizServiceImpl<BaseGroup> implements BaseGroupService {

    @Autowired
    private BaseGroupMapper baseGroupMapper;

    @Autowired
    private BaseUserMapper baseUserMapper;

    @Autowired
    private BaseMenuMapper baseMenuMapper;

    @Autowired
    private BaseElementMapper baseElementMapper;

    @Autowired
    private BaseTenantMapper baseTenantMapper;

    @Autowired
    private BaseResourceAuthorityService baseResourceAuthorityService;

    @Autowired
    private BaseAppOrderService baseAppOrderService;


    @Override
    public int insertSelective(BaseGroup entity) {
        if (AdminConstant.ROOT.equals(entity.getParentId())) {
            entity.setPath("/" + entity.getCode());
        } else {
            BaseGroup parent = this.selectById(entity.getParentId());
            entity.setPath(parent.getPath() + "/" + entity.getCode());
        }
        entity.setApplication(BaseContextHandler.getClientId());
        return super.insertSelective(entity);
    }

    @Override
    public int updateById(BaseGroup entity) {
        if (AdminConstant.ROOT == entity.getParentId()) {
            entity.setPath("/" + entity.getCode());
        } else {
            BaseGroup parent = this.selectById(entity.getParentId());
            entity.setPath(parent.getPath() + "/" + entity.getCode());
        }
        entity.setApplication(BaseContextHandler.getClientId());
        return super.updateById(entity);
    }

    /**
     * 获取群组关联用户
     *
     * @param groupId
     * @return
     */
    @Override
    public GroupUsers getGroupUsers(String groupId) {
        return new GroupUsers(baseUserMapper.selectMemberByGroupId(groupId), baseUserMapper.selectLeaderByGroupId(groupId));
    }

    /**
     * 变更群主所分配用户
     *
     * @param groupId
     * @param members
     * @param leaders
     */
//    @CacheClear(pre = "permission")
    @Override
    public void modifyGroupUsers(String groupId, String members, String leaders) {
        baseGroupMapper.deleteGroupLeadersById(groupId);
        baseGroupMapper.deleteGroupMembersById(groupId);
        if (!StringUtils.isEmpty(members)) {
            String[] mem = members.split(",");
            for (String m : mem) {
                baseGroupMapper.insertGroupMembersById(SnowFlakeUtil.getFlowIdInstance().nextId()+"", groupId, m, BaseContextHandler.getTenantId());
            }
        }
        if (!StringUtils.isEmpty(leaders)) {
            String[] mem = leaders.split(",");
            for (String m : mem) {
                baseGroupMapper.insertGroupLeadersById(SnowFlakeUtil.getFlowIdInstance().nextId()+"", groupId, m, BaseContextHandler.getTenantId());
            }
        }
    }

    /**
     * 变更群组关联的菜单
     *
     * @param groupId
     * @param menus
     */
//    @CacheClear(keys = {"permission:menu", "permission:u"})
    public void modifyAuthorityMenu(String groupId, String[] menus, String type) {
        baseResourceAuthorityService.deleteByAuthorityIdAndResourceType(groupId + "", AdminConstant.RESOURCE_TYPE_MENU, type);
        List<BaseMenu> menuList = baseMenuMapper.selectAll();
        Map<String, String> map = new HashMap<String, String>();
        for (BaseMenu menu : menuList) {
            map.put(menu.getId().toString(), menu.getParentId().toString());
        }
        Set<String> relationMenus = new HashSet<String>();
        relationMenus.addAll(Arrays.asList(menus));
        BaseResourceAuthority authority = null;
        for (String menuId : menus) {
            findParentID(map, relationMenus, menuId);
        }
        for (String menuId : relationMenus) {
            authority = new BaseResourceAuthority(AdminConstant.AUTHORITY_TYPE_GROUP, AdminConstant.RESOURCE_TYPE_MENU);
            authority.setAuthorityId(groupId + "");
            authority.setResourceId(menuId);
            authority.setParentId("-1");
            authority.setType(type);
            baseResourceAuthorityService.insertSelective(authority);
        }
    }

    private void findParentID(Map<String, String> map, Set<String> relationMenus, String id) {
        String parentId = map.get(id);
        if (String.valueOf(AdminConstant.ROOT).equals(id) || parentId == null) {
            return;
        }
        relationMenus.add(parentId);
        findParentID(map, relationMenus, parentId);
    }

    /**
     * SimpleRouteLocator
     * 分配资源权限
     *
     * @param groupId
     * @param menuId
     * @param elementId
     */
//    @CacheClear(keys = {"permission:ele", "permission:u"})
    @Override
    public void modifyAuthorityElement(String groupId, String menuId, String elementId, String type) {
        BaseResourceAuthority authority = new BaseResourceAuthority(AdminConstant.AUTHORITY_TYPE_GROUP, AdminConstant.RESOURCE_TYPE_BTN);
        authority.setAuthorityId(groupId + "");
        authority.setResourceId(elementId + "");
        authority.setParentId("-1");
        authority.setType(type);
        baseResourceAuthorityService.insertSelective(authority);
    }

    /**
     * 移除资源权限
     *
     * @param groupId
     * @param elementId
     */
//    @CacheClear(keys = {"permission:ele", "permission:u"})
    @Override
    public void removeAuthorityElement(String groupId, String elementId, String type) {
        BaseResourceAuthority authority = new BaseResourceAuthority();
        authority.setAuthorityId(groupId + "");
        authority.setResourceId(elementId + "");
        authority.setParentId("-1");
        authority.setType(type);
        baseResourceAuthorityService.delete(authority);
    }


    /**
     * 获取群主关联的菜单
     *
     * @param groupId
     * @return
     */
    @Override
    public List<MenuTree> getAuthorityMenu(String groupId, String type) {
        List<BaseMenu> menus = baseMenuMapper.selectMenuByAuthorityId(String.valueOf(groupId), AdminConstant.AUTHORITY_TYPE_GROUP, type);
        return MenuTree.buildTree(menus, AdminConstant.ROOT);
    }

    /**
     * 获取群组关联的资源
     *
     * @param groupId
     * @return
     */
    @Override
    public List<String> getAuthorityElement(String groupId, String type) {
        BaseResourceAuthority authority = new BaseResourceAuthority(AdminConstant.AUTHORITY_TYPE_GROUP, AdminConstant.RESOURCE_TYPE_BTN);
        authority.setAuthorityId(groupId);
        authority.setType(type);
        List<BaseResourceAuthority> authorities = baseResourceAuthorityService.selectList(authority);
        List<String> ids = new ArrayList<String>();
        for (BaseResourceAuthority auth : authorities) {
            ids.add(auth.getResourceId());
        }
        return ids;
    }

    /**
     * 获取当前管理员可以分配的菜单
     * @return
     */
    @Override
    public List<MenuTree> getAuthorizeMenus(String userId,String clientId) {
        BaseUser user = baseUserMapper.selectByPrimaryKey(userId);

        if (BooleanUtil.BOOLEAN_TRUE.equals(user.getIsSuperAdmin())) {
            return MenuTree.buildTree(baseMenuMapper.selectAll(), AdminConstant.ROOT);
        }
        BaseTenant tenant = baseTenantMapper.selectByPrimaryKey(user.getTenantId());

        //查询租户是否购买应用
        BaseAppOrder appOrder = baseAppOrderService.selectAppOrder(user.getTenantId(),clientId);

        if (null == appOrder){
            throw  new ClientTokenException("用户未购买应用:"+clientId);
        }

        List<BaseMenu> list = null;
        //租户管理员获取应用的菜单
        if (tenant.getOwner().equals(user.getId()))
        {
            list = baseMenuMapper.selectAuthorityMenuByAppId(appOrder.getAppId(),AdminConstant.RESOURCE_TYPE_AUTHORISE);
        }
        else
        {
            list = baseMenuMapper.selectAuthorityMenuByUserId(BaseContextHandler.getUserId(), AdminConstant.RESOURCE_TYPE_AUTHORISE);
        }
        return MenuTree.buildTree(list, AdminConstant.ROOT);
    }

    /**
     * 获取当前管理员可以分配的资源
     * @param menuId
     * @return
     */
//    @MergeResult
    @Override
    public List<BaseElement> getAuthorizeElements(String menuId) {
        BaseUser user = baseUserMapper.selectByPrimaryKey(BaseContextHandler.getUserId());

        if (BooleanUtil.BOOLEAN_TRUE.equals(user.getIsSuperAdmin())) {
            Example example = new Example(BaseElement.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("menuId", menuId);
            return baseElementMapper.selectByExample(example);
        }
        BaseTenant tenant = baseTenantMapper.selectByPrimaryKey(user.getTenantId());

        if (tenant.getOwner().equals(user.getId()))
        {
            return baseElementMapper.selectAuthorityMenuElementByTenantId(user.getTenantId(),menuId,AdminConstant.RESOURCE_TYPE_AUTHORISE);
        }

        return baseElementMapper.selectAuthorityMenuElementByUserId(BaseContextHandler.getUserId(),menuId,AdminConstant.RESOURCE_TYPE_AUTHORISE);
    }
}
